import Button from "@/component/Button";
import { Flex } from "@/component/Flex";
import { Input } from "@/component/Input";
import { IModalProps, Modal } from "@/component/Modal";
import { Tag } from "@/component/Tag";
import { Text } from "@/gimd/Text";
import useToast from "@/component/Toast";
import { ApiHttp } from "@/network/ApiHttp";
import { KnownError } from "@/network/Http";
import { useCallback, useEffect, useMemo, useState } from "react";
import { fetch_all_tags, ITag } from "@/api/fetch_all_tags";


export function ArticleTagsModal(props: IModalProps & { article_id?: any; }) {
  const [toast, ctx1] = useToast();
  const { article_id, ..._p } = props;
  const [tag_name, set_tag_name] = useState<string>();
  const [tag_submitting, set_tag_submitting] = useState(false);
  const [tag_deleting, set_tag_deleting] = useState(false);

  const [all_tags, set_all_tags] = useState<ITag[]>([]);
  const [deleted_tags, set_deleted_tags] = useState<ITag[]>([]);
  const [selected_tags, set_selected_tags] = useState<ITag[]>([]);

  const pending = tag_submitting || tag_deleting

  const deselected_tags = useMemo(() => {
    return all_tags.filter(a => {
      return !(selected_tags.find(b => a.id === b.id) || deleted_tags.find(b => a.id === b.id))
    })
  }, [selected_tags, all_tags, deleted_tags])

  const [refresh_flag, set_refresh_flag] = useState(0);
  useEffect(() => {
    if (typeof article_id !== 'number') return;
    const controller = new AbortController();
    fetch_all_tags(controller)
      .then(r => {
        const all_tags: ITag[] = r.data ?? []
        set_all_tags(all_tags)
        set_deleted_tags(a => a.filter(b => all_tags.find(c => b.id === c.id)))
        set_selected_tags(a => a.filter(b => all_tags.find(c => b.id === c.id)))
      })
      .catch(ApiHttp.ignoreAbort)
      .catch((e: any) => console.error(e));

    ApiHttp.get(`blog/list_article_tags_of_article`, { article_id_list: [article_id] }, { signal: controller.signal })
      .then(r => {
        set_selected_tags(r.data.map((v: any) => ({ id: v.tag_id, title: v.tag_title })))
      })
      .catch(ApiHttp.ignoreAbort)
      .catch((e: any) => console.error(e));

    return () => controller.abort();
  }, [refresh_flag, article_id]);

  const on_click_delete = useCallback((tag_id: any) => {
    const tag = all_tags?.find(v => v.id === tag_id);
    if (!tag) return alert('not found')
    set_deleted_tags(old => [...old.filter(item => item.id !== tag_id), tag])
  }, [all_tags])

  const on_click_cancel_delete = useCallback((tag_id: any) => {
    const tag = all_tags?.find(v => v.id === tag_id);
    if (!tag) return alert('not found')
    set_deleted_tags(old => [...old.filter(item => item.id !== tag_id)])
  }, [all_tags])

  const on_click_create = useCallback(() => {
    const url = `blog/save_article_tag`;
    const params = {};
    const body = { title: tag_name };
    set_tag_submitting(true);
    ApiHttp.post(url, params, body)
      .then(r => {
        set_tag_name('')
      }).catch((e: any) => {
        toast(KnownError.is(e) ? e.reply.msg : e);
      }).finally(() => {
        set_tag_submitting(false);
        set_refresh_flag(v => ++v)
      });
  }, [tag_name, toast])

  const on_click_select = useCallback((tag_id: any) => {
    const tag = all_tags?.find(v => v.id === tag_id);
    if (!tag) return alert('not found')
    set_selected_tags(old => [...old.filter(item => item.id !== tag_id), tag])
  }, [all_tags])

  const on_click_deselect = useCallback((tag_id: any) => {
    const tag = all_tags?.find(v => v.id === tag_id);
    if (!tag) return alert('not found')
    set_selected_tags(old => old.filter(item => item.id !== tag_id))
  }, [all_tags])

  const on_ok = async () => {
    const controller = new AbortController();

    if (deleted_tags.length) {
      set_tag_deleting(true)
      await ApiHttp.delete(`blog/del_article_tags`, { id_list: deleted_tags.map(v => v.id) }, { signal: controller.signal })
        .then(() => set_refresh_flag(v => ++v))
        .catch(ApiHttp.ignoreAbort)
        .catch((e: any) => console.error(e))
        .finally(() => set_tag_deleting(false));
    }

    set_tag_submitting(true)
    const body = { article_id, tag_id_list: selected_tags.map(v => v.id) }
    await ApiHttp.post(`blog/set_article_tags_of_article`, void 0, body, { signal: controller.signal })
      .catch(ApiHttp.ignoreAbort)
      .catch((e: any) => console.error(e))
      .finally(() => set_tag_submitting(false));

    toast('修改成功')
    set_refresh_flag(v => ++v)
  }

  return (
    <Modal
      title='编辑标签'
      open={!!article_id}
      styles={{ modal: { width: 400 } }}
      onOk={on_ok}
      {..._p}>
      {ctx1}
      <Flex gap={3} style={{ padding: 6, border: '1px solid #00000022', borderRadius: 3 }}>
        <Flex vertical gap={3} style={{ flex: 1 }}>
          <Text type='secondary' size='s'>
            待删除
          </Text>
          <Flex gap={3} wrap='wrap'>
            {deleted_tags?.map((v, idx) => (
              <Tag
                key={idx}
                suffix={
                  <Button
                    kind='icon'
                    size='s'
                    disabled={pending}
                    onClick={() => on_click_cancel_delete(v.id)}>
                    ➡
                  </Button>
                }>
                {v.title}
              </Tag>
            ))}
          </Flex>
        </Flex>
        <div style={{ width: 1, backgroundColor: '#00000022' }} />
        <Flex vertical gap={3} style={{ flex: 1 }}>
          <Text type='secondary' size='s'>
            全部
          </Text>
          <Flex gap={3} wrap='wrap'>
            {deselected_tags?.map((v, idx) => {
              return (
                <Tag
                  key={idx}
                  prefix={
                    <Button
                      kind='icon'
                      size='s'
                      disabled={pending}
                      onClick={() => on_click_delete(v.id)}>
                      ⬅
                    </Button>
                  }
                  suffix={
                    <Button
                      kind='icon'
                      size='s'
                      disabled={pending}
                      onClick={() => on_click_select(v.id)}>
                      ➡
                    </Button>
                  }>
                  {v.title}
                </Tag>
              );
            })}
          </Flex>
        </Flex>
        <div style={{ width: 1, backgroundColor: '#00000022' }} />
        <Flex vertical gap={3} style={{ flex: 1 }}>
          <Text type='secondary' size='s'>
            已选
          </Text>
          <Flex gap={3} wrap='wrap'>
            {selected_tags?.map((v, idx) => {
              return (
                <Tag
                  key={idx}
                  disabled={pending}
                  prefix={
                    <Button
                      kind='icon'
                      size='s'
                      disabled={pending}
                      onClick={() => on_click_deselect(v.id)}>
                      ⬅
                    </Button>
                  }>
                  {v.title}
                </Tag>
              );
            })}
          </Flex>
        </Flex>
      </Flex>
      <Input
        value={tag_name}
        maxLength={10}
        onChange={e => set_tag_name(e.target.value)}
        onBlur={e => set_tag_name(e.target.value.trim())} />
      <Button
        size='s'
        disabled={!tag_name || tag_submitting}
        onClick={on_click_create}>
        创建
      </Button>
    </Modal>
  );
}
